// Copyright (C) Microsoft Corporation. All rights reserved.

using System;
using System.Text;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Microsoft.DDSolutions.SharePoint;
using Microsoft.DDSolutions.SqlReportServer;
using Microsoft.DDSolutions.Tfs;
using Microsoft.TeamFoundation.Client;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Microsoft.DDSolutions.TfsAdmin.Tests
{
    /// <summary>
    /// This class contains unit tests for the TfsUnitTests class.
    /// </summary>
    [TestClass]
    public class TfsUnitTests
    {
        TfsServerProxy tfsProxy;
        TestConfig tc;
        TeamFoundationServer tfsServer;

        /// <summary>
        /// Creates a TFSServerProxy object, connects to the TFS host and obtains all project 
        /// information before running any unit tests.
        /// </summary>
        [TestInitialize]
        public void Init()
        {
            tc = TestConfig.Load("TestConfig.xml");
            tfsServer = TeamFoundationServerFactory.GetServer(tc.Server);
            tfsProxy = new TfsServerProxy();
            tfsProxy.IsProjectSite = true;
            
            // Perform common tfsProxy operations.

            tfsProxy.Connect(tfsServer);
            tfsProxy.GetAllProjectInfo();


            /// Make sure all the TFS Roles assigned for users in the config file actually
            /// exist on the TFS server.
            
            ReadOnlyCollection<string> actual = tfsProxy.GetProjectApplicationGroups(tc.TeamProject);

            foreach (DomainUser user in tc.DomainUsers)
            {
                /// Make sure the user has atleast one TFS Role assigned.
                Assert.IsTrue(user.TfsRoles.Length > 0, TestResource.strMissingRole);

                foreach (string tfsRole in user.TfsRoles)
                    CollectionAssert.Contains(actual, tfsRole, tfsRole + TestResource.MissingApplicationGroupMsg);
            }

            TfsAddUsers();
        }

        [TestCleanup]
        public void TeardownFixture()
        {
            TfsRemoveUsers();
        }

        #region Additional test attributes
        //
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // Use ClassCleanup to run code after all tests in a class have run
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // Use TestInitialize to run code before running each test 
        // [TestInitialize()]
        // public void MyTestInitialize() { }
        //
        // Use TestCleanup to run code after each test has run
        // [TestCleanup()]
        // public void MyTestCleanup() { }
        //
        #endregion

        /// <summary>
        /// Ensures that the returned project names are the expected projects on this TFS server.
        /// </summary>
        [TestMethod]
        public void TfsGetProjectNames()
        {
            ReadOnlyCollection<string> actual = tfsProxy.ProjectNames;

            CollectionAssert.Contains(actual, tc.TeamProject, TestResource.MissingProjectMsg + tc.TeamProject);
        }


        /// <summary>
        ///  Add users to TFS. This is invoked as part of TestClassSetup.
        /// </summary>
        public void TfsAddUsers()
        {
            bool caughtException = false;

            try
            {
                foreach (DomainUser user in tc.DomainUsers)
                {
                    string domainUserName = tc.GetDomainUserName(user.UserName);

                    foreach (string tfsRole in user.TfsRoles)
                    {
                        tfsProxy.AddUserToRole(domainUserName, tfsRole, tc.TeamProject);
                    }
                }
            }
            catch (InvalidTfsUserException)
            {
                caughtException = true;
            }

            Assert.IsTrue(caughtException == false,TestResource.TfsAddUserFailed);
        }

        
        public void TfsRemoveUsers()
        {
            bool caughtException = false;

            try
            {
                foreach (DomainUser user in tc.DomainUsers)
                {
                    tfsProxy.RemoveUser(tc.GetDomainUserName(user.UserName), tc.TeamProject);
                }
            }
            catch (InvalidTfsUserException)
            {
                caughtException = true;
            }

            Assert.IsTrue(caughtException == false, TestResource.TfsRemoveUserFailed);
        }

        /// <summary>
        /// Ensures that the collection of TFSUsers returned from GetAllUsers contains expected users.
        /// </summary>
        [TestMethod]
        public void TfsGetAllUsers()
        {

            Collection<TfsUser> actualTfsUsers = tfsProxy.GetAllUsers(tc.TeamProject);
            Collection<TfsUser> expectedTfsUsers = new Collection<TfsUser>();

            foreach(DomainUser user in tc.DomainUsers)
            {
                TfsUser tUser = new TfsUser(tc.GetDomainUserName(user.UserName));
                
                foreach(string tfsRole in user.TfsRoles)
                    tUser.AddRole(tfsRole,RoleType.TfsRole);

                expectedTfsUsers.Add(tUser);
            }

            foreach (TfsUser expectedUser in expectedTfsUsers)
            {
               Assert.IsTrue(actualTfsUsers.Contains(expectedUser), TestResource.MissingTfsUserMsg + expectedUser.Name);
            }

        }

        /// <summary>
        ///  Test if the tfs users added in TestClassSetup exist.
        /// </summary>
        [TestMethod]
        public void TfsIsUserExist()
        {
            foreach(DomainUser user in tc.DomainUsers)
            {
                Assert.IsTrue(tfsProxy.IsUserExist(tc.GetDomainUserName(user.UserName)), TestResource.MissingTfsUserMsg);
            }
        }

        /// <summary>
        /// Tests GetAllUsers behavior when passed a null project name.
        /// </summary>
        [TestMethod]
        public void TfsGetAllUsersNullProject()
        {
            bool caughtException = false;

            try
            {
                tfsProxy.GetAllUsers(null);
            }
            catch (ArgumentNullException)
            {
                caughtException = true;
            }

            Assert.IsTrue(caughtException, TestResource.GetAllUsersNoArgNullExecpMsg);

        }

       

        /// <summary>
        /// Tests GetProjectApplicationGroups behavior when passed a null project name.
        /// </summary>
        [TestMethod]
        public void TfsGetProjectApplicationGroupsNullProject()
        {
            bool caughtException = false;

            try
            {
                tfsProxy.GetProjectApplicationGroups(null);
            }
            catch (ArgumentNullException)
            {
                caughtException = true;
            }

            Assert.IsTrue(caughtException, TestResource.GetProjectApplicationGroupNoArgNullExecpMsg);
        }
    }
}
